package org.setamv.springcloud.ribbon.raw;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.client.ClientFactory;
import com.netflix.client.config.CommonClientConfigKey;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfigKey;
import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.config.ConfigurationManager;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;
import com.netflix.niws.client.http.RestClient;
import org.setamv.springcloud.dto.ApplicationProfile;
import org.setamv.springcloud.ribbon.rule.MyLoadBalanceRule;

import java.io.*;
import java.util.Arrays;
import java.util.List;

/**
 * 原始的ribbon使用方法starter<p>
 * 下面通过配置文件的方式使用ribbon的负载均衡
 */
public class RawRibbonUsageStarter {

    public static void  main(String[] args) throws Exception {
        String clientName = "sample-client";
        ConfigurationManager.loadPropertiesFromResources("ribbon-sample-client.properties");

        // 获取服务列表
        List<String> configServerList = (List<String>)ConfigurationManager.getConfigInstance().getProperty("sample-client.ribbon.listOfServers");
        System.out.println("Config server list " + configServerList);

        // 设置负载均衡的规则（也可以在配置文件ribbon-sample-client.properties中指定）
//        ConfigurationManager.getConfigInstance().setProperty("sample-client.ribbon.NFLoadBalancerRuleClassName", MyLoadBalanceRule.class.getName());

        RestClient client = (RestClient) ClientFactory.getNamedClient(clientName);
        HttpRequest request = HttpRequest.newBuilder().uri("/app/profile").build();
        for (int i = 0; i < 10; i++) {
            HttpResponse response = client.executeWithLoadBalancer(request);
            System.out.println(readResponse(response));
            response.close();
        }

        ZoneAwareLoadBalancer lb = (ZoneAwareLoadBalancer) client.getLoadBalancer();
        System.out.println(lb.getLoadBalancerStats());

        DefaultClientConfigImpl defaultClientConfig = DefaultClientConfigImpl.getClientConfigWithDefaultValues(clientName);
        IClientConfigKey<String> ruleConfigKey = new CommonClientConfigKey<String>("NFLoadBalancerRuleClassName") {
            @Override
            public Class<String> type() {
                return String.class;
            }
        };
        String ruleClassName = defaultClientConfig.get(ruleConfigKey);
        defaultClientConfig.set(ruleConfigKey, MyLoadBalanceRule.class.getName());

        // 更改服务列表
        ConfigurationManager.getConfigInstance().setProperty(
                "sample-client.ribbon.listOfServers", "www.setamv.tech:9092,www.setamv.tech:9091"); // 5
        System.out.println("changing servers ...");

        // 下面的为什么不起作用？
        // 更改负载均衡的规则，使用自定义的
//        ConfigurationManager.getConfigInstance().setProperty("sample-client.ribbon.NFLoadBalancerRuleClassName", MyLoadBalanceRule.class.getName());
//        System.out.println("changing load balance rule ...");

        // Wait until server list is refreshed (2 seconds refersh interval defined in properties file)
        Thread.sleep(3000);
        for (int i = 0; i < 10; i++)  {
            HttpResponse response = client.executeWithLoadBalancer(request);
            System.out.println(readResponse(response));
            response.close();
        }
        System.out.println(lb.getLoadBalancerStats());
    }


    private static final String readResponse(HttpResponse response) throws Exception {
        BufferedInputStream ins = new BufferedInputStream(response.getInputStream());
        StringBuilder sb = new StringBuilder();
        byte[] buf = new byte[1024];
        int len = -1;
        while ((len = ins.read(buf)) != -1) {
            sb.append(new String(buf, 0, len, "UTF-8"));
        }
        ObjectMapper mapper = new ObjectMapper();
        ApplicationProfile applicationProfile = mapper.readValue(sb.toString(), ApplicationProfile.class);

        StringBuilder responseSb = new StringBuilder();
        responseSb.append("Request url:").append(response.getRequestedURI()).append(", ")
                .append("status:").append(response.getStatus()).append("-").append(response.getStatusLine()).append(", ")
                .append("body:").append(applicationProfile);
        return responseSb.toString();
    }
}
